local skynet = require "skynet"
local cluster = require "skynet.cluster"
local filelog = require "filelog"
local timetool = require "timetool"
local json = require "cjson"
json.encode_sparse_array(true,1,1)

require "imenum"

local outofline_outtime = 7 * 24 * 3600     ---离线消息过期时间
local all_outtime = 7 * 24 * 3600           ---所有消息过期时间
local cache_message_num = 30                ---缓存消息的最多条数 

local function write_message(rid, message)
    local fields =  {
        rid = rid,
        keyid = message.keyid,
        sendrid = message.since_rid,
        destorid = message.send_to_rid,
        destoname = message.send_to_name,
        msg = message.msg,
        message_sendtime = message.sendtime,
    }
    if type(fields.content) == "table" then
        fields.content = json.encode(fields.content)
    end
    if fields.content and type(fields.content) ~= "string" then
        filelog.sys_error("error mail attach format!", rid, fields)
        return
    end
    local keyid = fields.keyid
    local status, result = skynet.pcall(cluster.call, "datanode", ".router", "insert_rk", rid, "rm_messagerecord", keyid, fields)
end


local function query_message(rid)
    local all_messages = {}
    local status, result = skynet.pcall(cluster.call, "datanode", ".router", "select_rk", rid, "rm_messagerecord")
    if not status or not result[1] or result[1] == 0 then
        return false, {}
    else
        return true, result[2]
    end
end

-- local function query_readstate(rid)
--     local read_state = {}
--     local status, result = skynet.pcall(cluster.call, "datanode", ".router", "select_rk", rid, "rm_readmessage")
--     if not status or not result[1] or result[1] == 0 then
--         return false, {}
--     else
--         return true, result[2]
--     end
-- end


local function delete_message(rid, keyid)
    cluster.send("datanode", ".router", "delete_rk", rid, "rm_messagerecord", keyid)
end



local Talkcachemgr = {
	CMD = {},
    cache_data = {},   ---缓存区域
}

function Talkcachemgr:getmessage(rid, send_to_rid)
    local resmessages = {}
    local talker_cache = Talkcachemgr.cache_data[rid]
    if not talker_cache or not talker_cache.message_cache[send_to_rid]then
        return false, resmessages
    else
        local temp_cache = talker_cache.message_cache[send_to_rid]
        for index, message in pairs(temp_cache) do
            table.insert(resmessages, message)
        end
        return true, resmessages
    end

end

function Talkcachemgr:getallmessage(rid)

end

function Talkcachemgr:delete_outtimemessage(rid, keyids)
    if not rid or not keyids then return end
    for index, keyid in ipairs(keyids) do
        delete_message(rid, keyid)
    end
end

function Talkcachemgr:init_cache(rid)
    local nowtime = timetool.get_time()
    if Talkcachemgr.cache_data[rid] == nil then
        Talkcachemgr.cache_data[rid] = {
            to_rids = {},
            message_cache = {},
        }
        local success, all_messages = query_message(rid)
        if success == true then
            local will_deletemessages = {}
            for keyid, message in pairs(all_messages) do
                if nowtime - message.message_sendtime > all_outtime then  ---检查过期消息
                    table.insert(will_deletemessages, keyid)
                else
                    if message.sendrid == rid and message.destorid ~= rid then
                        local oprid = message.destorid
                        if Talkcachemgr.cache_data[rid].message_cache[oprid] == nil then
                            Talkcachemgr.cache_data[rid].message_cache[oprid] = {}
                        end
                        table.insert(Talkcachemgr.cache_data[rid].message_cache[oprid], message)
                    elseif message.destorid == rid and message.sendrid ~= rid then
                        local oprid = message.sendrid
                        if Talkcachemgr.cache_data[rid].message_cache[oprid] == nil then
                            Talkcachemgr.cache_data[rid].message_cache[oprid] = {}
                        end
                        table.insert(Talkcachemgr.cache_data[rid].message_cache[oprid], message)
                    end
                end
            end
            ---filelog.sys_error("---------delete_outtimemessage-------", rid, will_deletemessages)
            Talkcachemgr:delete_outtimemessage(rid, will_deletemessages)
            for oprid, cache in pairs(Talkcachemgr.cache_data[rid].message_cache) do
                table.sort(Talkcachemgr.cache_data[rid].message_cache[oprid], 
                    function(first, second) 
                        if first.keyid < second.keyid then
                            return true
                        else
                            return false
                        end
                    end)
            end
        end
    end
end

function Talkcachemgr:save_incache(rid, send_to_rid, message)
    if Talkcachemgr.cache_data[rid] == nil then
        Talkcachemgr:init_cache(rid)
    end
    --local send_to_rid = message.send_to_rid
    local keyid = message.keyid
    local tmp_message = {
            rid     =  rid,
            keyid   = message.keyid,
            sendrid = message.since_rid,
            destorid = message.send_to_rid,
            destoname = message.send_to_name,
            msg     = message.msg,
            message_sendtime = message.sendtime,
    }
    if Talkcachemgr.cache_data[rid].message_cache[send_to_rid] == nil then
        Talkcachemgr.cache_data[rid].message_cache[send_to_rid] = {}
        table.insert(Talkcachemgr.cache_data[rid].message_cache[send_to_rid], tmp_message)
        Talkcachemgr:save_message(rid, message)
    else
        local is_already = false
        for index, messageitem in pairs(Talkcachemgr.cache_data[rid].message_cache[send_to_rid]) do
            if messageitem.keyid == keyid then
                is_already = true
            end
        end
        if not is_already then
            table.insert(Talkcachemgr.cache_data[rid].message_cache[send_to_rid], tmp_message)
            Talkcachemgr:save_message(rid, message)
        end
    end
    -----检查过期的消息
    local will_deletemessages = {}
    local nowtime = timetool.get_time()
    for send_to_rid, messages in pairs(Talkcachemgr.cache_data[rid].message_cache) do
        for index, message in pairs(messages) do
            if nowtime - message.message_sendtime > all_outtime then  ---检查过期消息
                table.insert(will_deletemessages, message.keyid)
                table.remove(messages, index)
            end
        end
        ----
    end
    ---删除过期消息
    Talkcachemgr:delete_outtimemessage(rid, will_deletemessages)
    ---filelog.sys_error("-----------save_incache------", rid, send_to_rid, Talkcachemgr.cache_data[rid].message_cache)
end

---检查离线玩家的过期消息
function Talkcachemgr:check_outlinemessage(rid)
    local nowtime = timetool.get_time()
    local success, all_messages = query_message(rid)
    if success == true then
        local will_deletemessages = {}
        for keyid, message in pairs(all_messages) do
            if nowtime - message.message_sendtime > outofline_outtime then  ---检查过期消息
                table.insert(will_deletemessages, keyid)
            end
        end
        Talkcachemgr:delete_outtimemessage(rid, will_deletemessages)
    end
end


function Talkcachemgr:save_message(rid, message)
    write_message(rid, message)
end

function Talkcachemgr:delete_message(rid, keyid)
    delete_message(rid, keyid)
end

function Talkcachemgr:clear_cache(rid)
    if Talkcachemgr.cache_data[rid] then
        Talkcachemgr.cache_data[rid] = nil
    end
end

function Talkcachemgr.CMD.init_talk_cache(rid)
    ---filelog.sys_error("-------Talkcachemgr.CMD.init_talk_cache---------", rid)
    Talkcachemgr:init_cache(rid)
end

function Talkcachemgr.CMD.get_alltalkrids(rid)
    ---filelog.sys_error("---------Talkcachemgr.CMD.get_alltalkrids---------", rid)
    local all_talkrids = {}
    if Talkcachemgr.cache_data[rid] and Talkcachemgr.cache_data[rid].message_cache 
        and next(Talkcachemgr.cache_data[rid].message_cache)  ~= nil then
        for talkrid, message in pairs(Talkcachemgr.cache_data[rid].message_cache) do
            if talkrid ~= rid then table.insert(all_talkrids, talkrid) end
        end
    end
    return all_talkrids
end

function Talkcachemgr.CMD.checkrid(rid)
	local is_exist = false
    local result = cluster.call("datanode", ".router", "select_rk", rid, "rs_info", true)
    if result[1] == 1 then
        is_exist = true
        return is_exist, result[2][rid]
    end
	return is_exist, nil
end


function Talkcachemgr.CMD.getmessagecache(rid, send_to_rid)
    local success, result = Talkcachemgr:getmessage(rid, send_to_rid)
    --filelog.sys_error("--------Talkcachemgr.CMD.getmessagecache--------success, result-----", success, result)
    if not success then
        return false, nil
    else
        return true, result
    end
end

function Talkcachemgr.CMD.pushmessageincache(rid, send_to_rid, message, is_on_im)
    if not is_on_im then
        Talkcachemgr:save_message(rid, message)
        Talkcachemgr:check_outlinemessage(rid)
    else
        Talkcachemgr:save_incache(rid, send_to_rid, message)
    end
end

function Talkcachemgr.CMD.deletemessage(rid, keyid)
    ----先从缓存中找,找到就删除再删除数据库中
    local nowtime = timetool.get_time()
    if Talkcachemgr.cache_data[rid] == nil then
        Talkcachemgr:init_cache(rid)
    end
    if Talkcachemgr.cache_data[rid] and Talkcachemgr.cache_data[rid].message_cache then
        for send_to_rid, cache in pairs(Talkcachemgr.cache_data[rid].message_cache) do
            for index, message in pairs(cache) do
                if message.keyid == keyid then
                    table.remove(cache, index)
                end
            end
        end
    end
    Talkcachemgr:delete_message(rid, keyid)
end

function Talkcachemgr.CMD.cleanmessages(rid, send_to_rid)
    if Talkcachemgr.cache_data[rid] == nil then
        Talkcachemgr:init_cache(rid)
    end
    if Talkcachemgr.cache_data[rid] and Talkcachemgr.cache_data[rid].message_cache then
        for sendtorid, cache in pairs(Talkcachemgr.cache_data[rid].message_cache) do
            if sendtorid == send_to_rid then
                for index, message in pairs(cache) do
                    Talkcachemgr:delete_message(rid, message.keyid)
                end
                Talkcachemgr.cache_data[rid].message_cache[sendtorid] = {}
            end
        end
    end
end

function Talkcachemgr.CMD.clearcache(rid)
    Talkcachemgr:clear_cache(rid)
end

function Talkcachemgr.CMD.get_forbidden_info(rid)
    
end

function Talkcachemgr:start()

end

skynet.start(function()
	skynet.dispatch("lua",function(session, source, cmd, ...)
        local f = Talkcachemgr.CMD[cmd]
        if f then
            skynet.retpack(f(...))
        else
            skynet.retpack()
        end
    end) 
	Talkcachemgr:start()
end) 